#include "astraldef.h"

#include "strapi.h"
#include "mapapi.h"
#include "_2device.h"
#include "queueapi.h"

static struct HashMap drvtable_ins;
static HashMap drvtable = &drvtable_ins;

DEFINE_QUEUE(reged_drv)

boolean register_driver(u32 mid, AstralDriver driver)
{
    boolean status = False;
    HashNode hn = find_object(drvtable, CAST_AS(object, mid));
    if (hn)
    {
        return False;
    }
    hn = (HashNode)ff_alloc(sizeof(struct HashNode));
    status = insert_object(drvtable, hn,
                           CAST_AS(object, mid),
                           CAST_AS(object, driver));
    if(status)
    {
        queue_push(reged_drv, &driver->reged);        
    }
    snprintf(driver->smid, 17,
             "%d.%d.%d.%d",
             MIDv4a(mid),
             MIDv4b(mid),
             MIDv4c(mid),
             MIDv4d(mid));
    return status;
}

u32 allocate_dynamic_mid()
{
    static u32 dmid = MIDv4(192, 0, 0, 0);
    //todo add atomic here
    dmid++;
    return dmid;
}

AstralDriver find_driver(u32 mid)
{
    HashNode hn = find_object(drvtable, CAST_AS(object, mid));
    if (!hn)
    {
        return NULL;
    }
    return CAST_AS(AstralDriver, hn->value);
}

void driver_manager_init()
{
    init_hashmap(drvtable);

    /**
     * find the static registered driver
     * we call these driver's registeration
     * function here.
     *
     * notice that memory should be ready.
     */
    executable *exec = get_drv_begin();
    executable *stop = get_drv_end();

    int size = stop - exec;
    for (; exec < stop; exec++)
    {
        if (*exec)
        {
            (*exec)(NULL);
        }
    }
    kprint("Total Static Registed Drivers: %d\n", size);
}


void list_driver()
{
    QueueNode n = NULL;
    AstralDriver d = NULL;
    n = reged_drv->first;
    while(n)
    {
        d = CONTAINER_OF(AstralDriver, reged, n);
        n = n -> next;
        kprint("%s, %s\n", d->smid, d->description);
    }
}